package com.tianji.promotion.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.dto.course.CategoryBasicDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.promotion.domain.dto.CouponFormDTO;
import com.tianji.promotion.domain.dto.CouponIssueFormDTO;
import com.tianji.promotion.domain.enums.CouponStatus;
import com.tianji.promotion.domain.enums.ObtainType;
import com.tianji.promotion.domain.po.Coupon;
import com.tianji.promotion.domain.po.CouponScope;
import com.tianji.promotion.domain.query.CouponQuery;
import com.tianji.promotion.domain.vo.CouponDetailVO;
import com.tianji.promotion.domain.vo.CouponPageVO;
import com.tianji.promotion.domain.vo.CouponScopeVO;
import com.tianji.promotion.domain.vo.CouponVO;
import com.tianji.promotion.mapper.CouponMapper;
import com.tianji.promotion.service.ICouponScopeService;
import com.tianji.promotion.service.ICouponService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.promotion.service.IExchangeCodeService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 优惠券的规则信息 服务实现类
 * </p>
 *
 * @author author
 * @since 2025-03-29
 */
@Service
@RequiredArgsConstructor
public class CouponServiceImpl extends ServiceImpl<CouponMapper, Coupon> implements ICouponService {

    private final ICouponScopeService couponScopeService;
    private final CategoryCache categoryCache;
    private final IExchangeCodeService exchangeCodeService;
    /**
     * 新增优惠卷
     *
     * @param couponFormDTO
     */
    @Override
    @Transactional
    public void addCoupon(CouponFormDTO couponFormDTO) {
        Coupon coupon = BeanUtils.copyBean(couponFormDTO, Coupon.class);
        this.save(coupon);

        if (!coupon.getSpecific()) {
            return;
        }

        List<Long> scopes = couponFormDTO.getScopes();
        if (CollUtils.isEmpty(scopes)) {
            throw new BadRequestException("优惠券使用范围不能为空");
        }
        List<CouponScope> scopeList = new ArrayList<>();
        for (Long scope : scopes) {
            CouponScope tmp = new CouponScope();
            tmp.setCouponId(coupon.getId());
            tmp.setBizId(scope);
            tmp.setType(1);
            scopeList.add(tmp);
        }
        couponScopeService.saveBatch(scopeList);
    }

    /**
     * 分页查询优惠卷
     *
     * @param couponQuery
     * @return
     */
    @Override
    public PageDTO<CouponPageVO> pageQuery(CouponQuery couponQuery) {
        Page<Coupon> pageResult = this.lambdaQuery()
                .eq(couponQuery.getStatus() != null, Coupon::getStatus, couponQuery.getStatus())
                .eq(couponQuery.getType() != null, Coupon::getType, couponQuery.getType())
                .like(couponQuery.getName() != null, Coupon::getName, couponQuery.getName())
                .page(couponQuery.toMpPageDefaultSortByCreateTimeDesc());

        List<CouponPageVO> records = BeanUtils.copyList(pageResult.getRecords(), CouponPageVO.class);
        return PageDTO.of(pageResult, records);
    }

    /**
     * 根据id返显优惠卷信息
     *
     * @param id
     * @return
     */
    @Override
    public CouponDetailVO getDetailById(Long id) {
        Coupon coupon = this.getById(id);
        if (coupon != null) {
            CouponDetailVO detailVO = BeanUtils.copyBean(coupon, CouponDetailVO.class);
            List<CouponScope> scopes = couponScopeService.lambdaQuery()
                    .eq(CouponScope::getCouponId, id)
                    .list();
            List<CouponScopeVO> scopeList = new ArrayList<>();

            // 根据范围id拿到范围的名称
            Map<Long, CategoryBasicDTO> categoryMap = categoryCache.getCategoryMap();
            for (CouponScope scope : scopes) {
                Long bizId = scope.getBizId();
                if (scope.getType() == 1) {
                    CategoryBasicDTO category = categoryMap.get(bizId);
                    scopeList.add(new CouponScopeVO(bizId, category.getName()));
                }
            }
            detailVO.setScopes(scopeList);

            return detailVO;
        }
        return null;
    }

    /**
     * 根据id更新优惠卷信息
     *
     * @param couponFormDTO
     */
    @Override
    @Transactional
    public void updateDetailById(CouponFormDTO couponFormDTO) {
        Coupon coupon = BeanUtils.copyBean(couponFormDTO, Coupon.class);
        this.updateById(coupon);

        if (coupon.getSpecific()) {
            // 批量删除优惠卷范围中所有相关记录
            couponScopeService.lambdaUpdate()
                    .eq(CouponScope::getCouponId, couponFormDTO.getId())
                    .remove();

            // 再批量新增
            List<Long> scopes = couponFormDTO.getScopes();
            if (CollUtils.isNotEmpty(scopes)) {
                List<CouponScope> scopeList = new ArrayList<>();
                for (Long scope : scopes) {
                    CouponScope tmp = new CouponScope();
                    tmp.setCouponId(couponFormDTO.getId());
                    tmp.setBizId(scope);
                    scopeList.add(tmp);
                }
                couponScopeService.saveBatch(scopeList);
            }
        }
    }

    /**
     * 发放优惠卷
     *
     * @param issueDTO
     */
    @Override
    public void issueCoupon(CouponIssueFormDTO issueDTO) {
        // 1、查询优惠券
        Coupon coupon = this.getById(issueDTO.getId());
        if (coupon == null) {
            throw new BadRequestException("优惠券不存在");
        }

        // 2、判断优惠券状态，是暂停还是待发放
        if (coupon.getStatus() != CouponStatus.DRAFT && coupon.getStatus() != CouponStatus.PAUSE) {
            throw new BizIllegalException("优惠券状态错误!");
        }

        // 3、判断优惠券发放时间，是否在范围内
        LocalDateTime beginTime = issueDTO.getIssueBeginTime();
        LocalDateTime endTime = issueDTO.getIssueEndTime();
        LocalDateTime now = LocalDateTime.now();
        // 判断是否是立刻发放
        boolean isBegin = beginTime == null || !now.isBefore(beginTime);
        // 更新优惠券
        // 拷贝属性到Po
        Coupon coupon1 = BeanUtils.copyBean(coupon, Coupon.class);
        // 更新状态
        if (isBegin) {
            coupon1.setStatus(CouponStatus.ISSUING);
            coupon1.setIssueBeginTime(now);
        } else {
            coupon1.setStatus(CouponStatus.UN_ISSUE);
        }
        // 更新数据库
        this.updateById(coupon1);

        // 判断是否需要生成兑换码，优惠券类型必须是兑换码，优惠券状态必须是待发放
        if (coupon.getObtainWay() == ObtainType.ISSUE && coupon.getStatus() == CouponStatus.DRAFT) {
            coupon1.setIssueEndTime(endTime);
            exchangeCodeService.asyncGenerateCode(coupon1);
        }
    }


}
